/*
 * SchedulerFetchRepository.java
 * Copyright: Tsingsoft (c) 2015
 * Company: 北京清软创新科技有限公司
 */
package org.liang.job.repository;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.liang.jdbc.repository.BaseRepository;
import org.liang.job.beans.Cron;
import org.liang.job.beans.JobInfo;
import org.liang.job.beans.TriggerInfo;
import org.liang.job.repository.mapper.JobInfoRowMapper;
import org.liang.job.repository.mapper.TriggerInfoRowMapper;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

/**
 * 自动任务查询数据操作类.
 * 
 * <pre>
 * 提供以下行为：
 *  1. 查询所有任务
 *  2. 根据任务编号查询任务信息
 *  3. 按组查询 任务信息
 *  4. 根据任务标题 查询任务（模糊查询）
 *  5. 根据任务信息查询 任务触发器
 *  6. 根据任务编号获取查询 任务触发器
 *  7. 查询所有触发器信息
 *  8. 根据组查询触发器
 *  9. 根据触发字符串 查询触发器
 *  10. 根据任务编号获取任务参数
 * </pre>
 *
 * @author L.Yang
 * @version 1.0, 2015年10月9日
 */
@Repository("schedulerFetchRepository")
public class SchedulerFetchRepository extends BaseRepository {

    @Autowired
    private Scheduler scheduler;

    /**
     * 查询所有任务.
     * 
     * @return 任务信息
     */
    public List<JobInfo> queryAllJobs() {
        StringBuilder sql = new StringBuilder(getGeneralSQL4Job());
        sql.append("order by CREATETIME");
        return getJdbcTemplate().query(sql.toString(), new JobInfoRowMapper());
    }

    /**
     * 根据ID查询任务信息.
     * 
     * @param jobId
     *            任务编号
     * @return 任务信息
     */
    public JobInfo queryJobById(String jobId) {
        StringBuilder sql = new StringBuilder(getGeneralSQL4Job());
        sql.append("and t.ID = ? ").append("order by CREATETIME");
        return getJdbcTemplate().queryForObject(sql.toString(),
                        new Object[] {jobId}, new JobInfoRowMapper());
    }

    /**
     * 按组查询 任务信息.
     * 
     * @param groupId
     *            组编号
     * @return 任务信息
     */
    public List<JobInfo> queryJobsByGroupId(String groupId) {
        StringBuilder sql = new StringBuilder(getGeneralSQL4Job());
        sql.append("and j.GROUP_ID = ? ").append("order by CREATETIME");
        return getJdbcTemplate().query(sql.toString(),
                        new Object[] {groupId}, new JobInfoRowMapper());
    }

    /**
     * 根据任务标题 查询任务（模糊查询）.
     * 
     * @param title
     *            任务标题
     * @return 任务信息
     */
    public List<JobInfo> queryJobsByTitle(String title) {
        StringBuilder sql = new StringBuilder(getGeneralSQL4Job());
        sql.append("and t.TITLE like '%?%' ").append("order by CREATETIME");
        return getJdbcTemplate().query(sql.toString(),
                        new Object[] {title}, new JobInfoRowMapper());
    }

    /**
     * 根据任务查询任务参数.
     * 
     * @param jobId
     *            任务编号
     * @return 该任务的所有参数
     */
    public List<Map<String, Object>> fetchParamsByJobId(String jobId) {
        String sql = "select * from TASK_JOB_PARAM p where p.JOB_ID = ? order by NEXT_FIRE_TIME";
        return getJdbcTemplate().queryForList(sql, jobId);
    }

    /**
     * 根据任务查询任务参数.
     * 
     * @param jobId
     *            任务编号
     * @return 该任务的所有参数
     */
    public List<Cron> fetchCronsByJobId(String jobId) {
        StringBuilder sql = new StringBuilder();
        try {
            sql.append("select c.TRIGGER_GROUP,c.CRON_EXPRESSION ")
                .append("from QRTZ_CRON_TRIGGERS c, ")
                .append("TASK_AUTO_JOB j, ").append("QRTZ_TRIGGERS t ")
                .append("where t.JOB_GROUP = jg.ID ")
                .append("and t.TRIGGER_GROUP = tg.ID ")
                .append("and t.JOB_NAME = j.`NAME` ")
                .append("and t.JOB_GROUP = j.GROUP_ID ")
                .append("and t.TRIGGER_NAME = c.TRIGGER_NAME ")
                .append("and t.TRIGGER_GROUP = c.TRIGGER_GROUP ")
                .append("and t.SCHED_NAME = c.SCHED_NAME ")
                .append("and t.SCHED_NAME = '").append(scheduler.getSchedulerName()).append("' ")
                .append("and j.ID = ?");
        } catch (SchedulerException e) {
            logger.error("获取quartz实例名 异常 :{}" + ExceptionUtils.getStackTrace(e));
        }
        return getJdbcTemplate().query(sql.toString(), new Object[] {jobId}, new RowMapper<Cron>() {
            @Override
            public Cron mapRow(ResultSet rs, int rowNum) throws SQLException {
                return new Cron(rs.getString("CRON_EXPRESSION"), rs.getString("TRIGGER_GROUP"));
            }
        });
    }

    /**
     * 根据任务信息查询 任务触发器.
     * 
     * @param jobid
     *            任务编号
     * @return 触发器信息（包含任务信息）
     */
    public List<TriggerInfo> fetchTriggersByJobId(String jobid) {
        StringBuilder sql = new StringBuilder(getGeneralSQL4Trigger());
        sql.append("and j.ID = ? ")
            .append("order by t.NEXT_FIRE_TIME ");
        return getJdbcTemplate().query(sql.toString(),
                        new Object[] {jobid}, new TriggerInfoRowMapper());
    }

    /**
     * 查询所有触发器信息.
     * 
     * @return 触发器信息（包含任务信息）
     */
    public List<TriggerInfo> queryAllTriggers() {
        StringBuilder sql = new StringBuilder(getGeneralSQL4Trigger());
        sql.append("order by t.NEXT_FIRE_TIME ");
        return getJdbcTemplate().query(sql.toString(), new TriggerInfoRowMapper());
    }

    /**
     * 根据组查询触发器.
     * 
     * @param triggerGroup
     *            触发器组
     * @return 触发器信息（包含任务信息）
     */
    public List<TriggerInfo> queryTriggersByGroup(String triggerGroup) {
        StringBuilder sql = new StringBuilder(getGeneralSQL4Trigger());
        sql.append(" and t.TRIGGER_GROUP = ? order by t.NEXT_FIRE_TIME ");
        return getJdbcTemplate().query(sql.toString(),
                        new Object[] {triggerGroup}, new TriggerInfoRowMapper());
    }

    /**
     * 根据触发字符串 查询触发器.
     * 
     * @param cronExpression
     *            触发器的时间字符串
     * @return 触发器信息（包含任务信息）
     * @throws SchedulerException
     *             quartz 获取 SchedulerName 抛出异常
     */
    public List<TriggerInfo> queryTriggersByCron(String cronExpression) {
        StringBuilder sql = new StringBuilder();
        try {
            sql.append(getGeneralSQL4Trigger())
                .append("and t.TRIGGER_GROUP || t.TRIGGER_NAME IN ( ")
                .append("   SELECT ")
                .append("   c.TRIGGER_NAME || c.TRIGGER_GROUP ").append("from ")
                .append("   QRTZ_CRON_TRIGGERS c, ").append("   QRTZ_TRIGGERS _t ")
                .append("where ").append("  c.SCHED_NAME = _t.SCHED_NAME ")
                .append("and c.CRON_EXPRESSION = ? ").append(") ")
                .append("and c.SCHED_NAME = '").append(scheduler.getSchedulerName()).append("') ")
                .append("order by t.NEXT_FIRE_TIME");
        } catch (SchedulerException e) {
            logger.error("获取quartz实例名 异常 :{}" + ExceptionUtils.getStackTrace(e));
        }
        return getJdbcTemplate().query(sql.toString(),
                        new Object[] {cronExpression}, new TriggerInfoRowMapper());
    }

    /**
     * 获取 通用Trigger查询SQL（包含任务信息）.
     */
    private String getGeneralSQL4Trigger() {
        StringBuilder sql = new StringBuilder();
        try {
            sql.append("select j.ID JOB_ID, j.TITLE, j.BIZ, ")
                .append("t.JOB_NAME, t.JOB_GROUP, jg.`NAME` JOB_GROUP_NAME, ")
                .append("t.TRIGGER_NAME, t.TRIGGER_GROUP, tg.`NAME` TRIGGER_GROUP_NAME, t.PRIORITY, ")
                .append("t.TRIGGER_STATE, t.PREV_FIRE_TIME, t.NEXT_FIRE_TIME, ")
                .append("t.START_TIME, t.END_TIME ")
                .append("from QRTZ_TRIGGERS t, ").append("  TASK_AUTO_JOB j, ")
                .append("   TASK_JOB_GROUP jg, ").append("  TASK_TRIGGER_GROUP tg ")
                .append("where t.JOB_GROUP = jg.ID ")
                .append("and t.TRIGGER_GROUP = tg.ID ")
                .append("and t.JOB_NAME = j.`NAME` ")
                .append("and t.JOB_GROUP = j.GROUP_ID ")
                .append("and t.SCHED_NAME = '").append(scheduler.getSchedulerName()).append("' ");
        } catch (SchedulerException e) {
            logger.error("获取quartz实例名 异常 :{}" + ExceptionUtils.getStackTrace(e));
        }
        return sql.toString();
    }

    /** 获取 通用JOB查询SQL. */
    private String getGeneralSQL4Job() {
        StringBuilder sql = new StringBuilder();
        sql.append("select j.ID, j.TITLE, j.`NAME`, j.GROUP_ID, g.`NAME` GROUP_NAME, ")
            .append("j.BIZ, j.CREATETIME, j.UPDATETIME ")
            .append("from TASK_AUTO_JOB j, ").append("  TASK_JOB_GROUP g ")
            .append("where  j.GROUP_ID = g.ID ");
        return sql.toString();
    }
}
